package com.hfzy.ihk.web.websocket.support.toBrowser.handler;

import com.alibaba.fastjson.JSONObject;
import com.hfzy.ihk.common.util.date.DateUtils;
import com.hfzy.ihk.web.websocket.conf.PublicConfig;
import com.hfzy.ihk.web.websocket.constant.Constants;
import com.hfzy.ihk.web.websocket.support.WebSocketManager;
import com.hfzy.ihk.web.websocket.support.base.WebSocketMessageHandler;
import com.hfzy.ihk.web.websocket.support.base.AbstractBrowserWebSocketHandler;
import com.hfzy.ihk.web.websocket.utils.SpringWebSocketUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.web.socket.*;

import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Created by Administrator on 2016/11/20.
 *
 * @author wws
 */
public class BrowserWebSocketHandler extends AbstractBrowserWebSocketHandler {

    private static final Logger logger = LoggerFactory.getLogger(BrowserWebSocketHandler.class);

    @Autowired
    private BrowserWebSocketMessageHandler browserWebSocketMessageHandler;



    /**
     * 链接成功以后调用
     * 现在的规则是，一个用户不能再两台电脑以上有链接，如果有会询问是否切换电脑，
     * 但是在同一台机器上可以有最多两个websocket链接
     *
     *
     * @param session
     * @throws Exception
     */
    @Override
    public void afterConnectionEstablished(WebSocketSession session) throws Exception {

        Map<String,Object> attributes = session.getAttributes();

        String zyUserId = (String)attributes.get("userId");
        String token = (String)attributes.get("token");
        String currentMachineId = (String)attributes.get("machineId");

        if(currentMachineId != null) {//生产机token格式是 <machineId_timestamp>

            Map<String, List<WebSocketSession>> machineWebSocketListMap = WebSocketManager.getBrowserUserMahineWebSocketSessionsMap().get(zyUserId);

            if(machineWebSocketListMap == null || machineWebSocketListMap.isEmpty()){//未有机器的websocket连接

                WebSocketManager.browserTokenWebSocketSessionMap.put(token,session);
                WebSocketManager.addBrowserUserMachineWebSocketSession(zyUserId,currentMachineId,session);
                WebSocketManager.browserUserTokenWebSocketSessionMap.put(zyUserId+token,session);

                Map<String, String> map  = new HashMap<>();
                map.put(Constants.WEB_SOCKET_JSON_KEY_MSG_TYPE, Constants.WEB_SOCKET_MSG_TYPE_WEBSOCKET);
                map.put(Constants.WEB_SOCKET_JSON_KEY_CODE, Constants.SUCCESS_1);
                map.put(Constants.WEB_SOCKET_JSON_KEY_DESC, Constants.LOCAL_MSG_WEBSOCKET_CONNECT_CAN_USE);
                map.put(Constants.WEB_SOCKET_JSON_KEY_TIME, DateUtils.formatDate(new Date(), DateUtils.DATE_FORMAT_DATETIME_SSS));

                //{"msgType":"WEBSOCKET_CONNECT_MSG","code":"1","time":"20161109145228476","desc":"websocket连接可用"}
                SpringWebSocketUtils.pushToClient(session, JSONObject.toJSONString(map));

                logger.info("未有机器的websocket连接: userId:{},token:{}",zyUserId,token);
            }else {//已有机器的连接

                List<WebSocketSession> webSocketList = machineWebSocketListMap.get(currentMachineId);

                Map<String, String> map  = new HashMap<>();

                //且，当前机器没有连接
                if(webSocketList == null || webSocketList.isEmpty()){
                    //返回消息，询问是否切换电脑进行外呼

                    map.put(Constants.WEB_SOCKET_JSON_KEY_MSG_TYPE, Constants.WEB_SOCKET_MSG_TYPE_WEBSOCKET);
                    map.put(Constants.WEB_SOCKET_JSON_KEY_CODE, Constants.FAIL);
                    map.put(Constants.WEB_SOCKET_JSON_KEY_DESC, Constants.LOCAL_EXCEPTION_13);
                    map.put(Constants.WEB_SOCKET_JSON_KEY_TIME, DateUtils.formatDate(new Date(), DateUtils.DATE_FORMAT_DATETIME_SSS));

                    //{"msgType":"WEBSOCKET_CONNECT_MSG","code":"-1","time":"20161109145228476",
                    // "desc":"请不要使用多台电脑外呼。如果要切换到此台电脑外呼，上一台电脑将停止外呼。"}
                    SpringWebSocketUtils.pushToClient(session, JSONObject.toJSONString(map));

                    logger.info("当前用户有其他机器的连接({})，当前机器没有连接: userId:{},token:{}",WebSocketManager.getBrowserMachineSessionSizeDesc(zyUserId),
                            zyUserId,token);

                }else {//同一台机器，允许多个websocket连接

                    WebSocketManager.browserTokenWebSocketSessionMap.put(token,session);
                    WebSocketManager.addBrowserUserMachineWebSocketSession(zyUserId,currentMachineId,session);
                    WebSocketManager.browserUserTokenWebSocketSessionMap.put(zyUserId+token,session);

                    //如果同机器限制websocket连接数，并且达到限制数
                    if(PublicConfig.webSocketSameMachineThreshold > 0 && webSocketList.size() > PublicConfig.webSocketSameMachineThreshold) {
                        map.put(Constants.WEB_SOCKET_JSON_KEY_MSG_TYPE, Constants.WEB_SOCKET_MSG_TYPE_TOO_MANY_CONNECT);
                        map.put(Constants.WEB_SOCKET_JSON_KEY_CODE, Constants.FAIL);
                        map.put(Constants.WEB_SOCKET_JSON_KEY_DESC, "请勿使用" + PublicConfig.webSocketSameMachineThreshold + "个以上窗口或浏览器进行外呼");
                        map.put(Constants.WEB_SOCKET_JSON_KEY_TIME, DateUtils.formatDate(new Date(), DateUtils.DATE_FORMAT_DATETIME_SSS));

                        //关闭连接
                        if(session.isOpen()) {
                            SpringWebSocketUtils.pushToClient(session, JSONObject.toJSONString(map));
                            session.close();
                        }
                        logger.info("同一台机器，websocket连接过多: userId:{},token:{},connect size:{}", zyUserId, token, webSocketList.size());
                    } else {

                        map.put(Constants.WEB_SOCKET_JSON_KEY_MSG_TYPE, Constants.WEB_SOCKET_MSG_TYPE_WEBSOCKET);
                        map.put(Constants.WEB_SOCKET_JSON_KEY_CODE, Constants.SUCCESS_1);
                        map.put(Constants.WEB_SOCKET_JSON_KEY_DESC, Constants.LOCAL_MSG_WEBSOCKET_CONNECT_CAN_USE);
                        map.put(Constants.WEB_SOCKET_JSON_KEY_TIME, DateUtils.formatDate(new Date(), DateUtils.DATE_FORMAT_DATETIME_SSS));

                        //{"msgType":"WEBSOCKET_CONNECT_MSG","code":"1","time":"20161109145228476","desc":"websocket连接可用"}
                        SpringWebSocketUtils.pushToClient(session, JSONObject.toJSONString(map));

                        logger.info("同一台机器，允许多个websocket连接: userId:{},token:{},connect size:{}", zyUserId, token, webSocketList.size());
                    }
                }

            }

        }else {//兼容测试机
            WebSocketManager.browserTokenWebSocketSessionMap.put(token,session);
        }

    }

    @Override
    public void handleMessage(WebSocketSession session, WebSocketMessage<?> message) throws Exception {
        browserWebSocketMessageHandler.handleMessage(session,message);
    }

    @Override
    public void afterConnectionClosed(WebSocketSession session, CloseStatus closeStatus) throws Exception {

        Map<String,Object> attributes = session.getAttributes();

        String userId = (String)attributes.get("userId");
        String token = (String)attributes.get("token");
        String machineId = (String)attributes.get("machineId");

        logger.info("afterConnectionClosed: userId:{},machineId:{},token:{}, close reason:{}",userId,machineId,token,closeStatus.getReason());

        /**删除关系*/
        WebSocketManager.removeUserBrowserWebSocketSession(userId,token,machineId,session);

    }

}
